<?php

namespace Modules\Production\Repository;

use App\Services\UnitService;
use Illuminate\Support\Facades\DB;
use Modules\Production\Models\ProductionProcess;
use Modules\Production\Models\ProductionProcessDetail;

/**
 * 工序报工相关
 * Class ProcessDetailRepository
 * @package Modules\Production\Repository
 */
class ProcessDetailRepository
{

    /**
     * 根据生产工单工序查找工序工单信息
     * @param $qrcode
     * @return mixed
     */
    static public function getById($qrcode){
        $qrcode = explode('@',$qrcode);
        if(count($qrcode) != 2){
            throw new \Exception('二维码数据格式有误');
        }
        $process = ProductionProcess::with('order')->find($qrcode[1]);
        if(!$process){
            throw new \Exception("工序【{$qrcode[1]}】不存在");
        }

        $process = $process->toArray();

        //上级工序
        $process['prev_process'] = self::getProcessById($process['parent_id']);

        if(empty($process['prev_process'])){
            $process['prev_report_qty'] = 0;
            $process['allow_report_qty'] = 0;
        }else{
            $process['prev_report_qty'] = floatval($process['prev_process']->make_qty);
            $process['allow_report_qty'] = $process['prev_process']->make_qty - $process['make_qty'];
        }

        return $process;
    }

    /**
     * 根据id查询一条工单汇报工序
     * @param $id
     * @return mixed
     */
    static public function getProcessDetailById($id){
        return ProductionProcessDetail::find($id);
    }

    static public function getProcessById($id){
        return ProductionProcess::find($id);
    }

    /**
     * 查询下级工艺
     * @param $parentId
     */
    static public function getSonProcessById($id){
        return ProductionProcess::where('parent_id',$id)->first();
    }

    /**
     * 将已汇报明细设为未汇报
     * @param $ids
     * @return mixed
     */
    static public function resetProcessDetailReport($ids){
        return ProductionProcessDetail::whereIn('id',$ids)->update([
            'is_report' => 0
        ]);
    }

    /**
     * 工序报工明细保存
     * @param $postData
     * @return bool
     * @throws \Throwable
     */
    static public function save($postData){

        $process = ProductionProcess::with('order')->find($postData['process_id']);

        if($process->parent_id == 0){
            //第一步工序，判断当前工序汇报的数量不能大于总生产量
            if( ($process->make_qty + $postData['report_qty']) > $process->order->fqty){
                //throw new \Exception('汇报数量不能大于总生产数量');
            }
        }else{
            //有上级工序，不能大于上级工序汇报的数量
            $lsatProcess = ProductionProcess::find($process->parent_id);
            if( ($process->make_qty + $postData['report_qty']) > $lsatProcess->make_qty){
                throw new \Exception('当前工序汇报数量不能大于上级工序汇报数量' . $lsatProcess->report_qty);
            }
        }
        try{
            DB::beginTransaction();
            $total_hours = ($postData['people'] * $postData['hours']);
            (new ProductionProcessDetail())->storeBy([
                'process_id'    => $process->id,
                'process_code'  => $process->process_code,
                'process_name'  => $process->process_name,
                'report_qty'    => $postData['report_qty'],
                'people'        => $postData['people'],
                'hours'         => $postData['hours'],
                'total_hours'   => $total_hours,
            ]);

            ProductionProcess::where('id',$process->id)->increment('make_qty',$postData['report_qty']);
            ProductionProcess::where('id',$process->id)->increment('total_hours',$total_hours);
            DB::commit();
            return true;
        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }

    }

    /**
     * 根据工单id获取工序及工序汇报明细
     * @param $productionId
     * @param null $isReport 工序是否已汇报金蝶 0否，1是
     * @return mixed
     */
    static public function getProcessExtendDetailByProductionId($productionId,$isReport = null){

        $processDetailModel = new ProductionProcess();

        if($isReport !== null){
            $processDetailModel = $processDetailModel->with(['detail' => function($query) use ($isReport){
                $query->where('is_report',$isReport);
            }]);
        }else{
            $processDetailModel = $processDetailModel->with('detail');
        }

        return $processDetailModel->where('production_order_id',$productionId)->orderBy('sort','desc')->get();
    }

    /**
     * 设置指定id的报工明细为已汇报
     * @param array $ids
     * @return mixed
     */
    static public function updateProcessDetailToReport(array $ids){
        return ProductionProcessDetail::whereIn('id',$ids)->update(['is_report'=>1]);
    }

    /**
     * 获取指定工单id汇报的总工时
     * @param $productionId
     * @return mixed
     */
    static public function getTotalHoursByProductionId($productionId){
        return ProductionProcess::where('production_order_id',$productionId)->sum('total_hours');
    }

    /**
     * 获取指定工单id汇报的总数量
     * @param $productionId
     * @return mixed
     */
    static public function getTotalReportQtyProductionId($productionId){
        return ProductionProcess::where('production_order_id',$productionId)->sum('total_hours');
    }

    /**
     * 获取工单最后一道工序信息
     * @param $productionId
     * @return mixed
     */
    static public function getLastProcess($productionId){
        return ProductionProcess::where('production_order_id',$productionId)->orderBy('sort','desc')->first();
    }

    /**
     * 工序报工明细删除
     * @param $id
     */
    static public function deleteBy($id){

        $processDetail = self::getProcessDetailById($id);

        if(!$processDetail){
            throw new \Exception("工序报工明细ID[{$id}]不存在");
        }

        if($processDetail->is_report != 0){
            throw new \Exception("工序报工已汇报，请先删除对应汇报单");
        }

        //查询对应工艺
        $process = self::getProcessById($processDetail->process_id);
        //下级工艺
        $sonProcess = self::getSonProcessById($process->id);
        if($sonProcess && ($process->make_qty - $processDetail->report_qty) < $sonProcess->make_qty){
            throw new \Exception("删除失败，当前工艺报工总数量不能小于[{$sonProcess->process_name}]报工总数量");
        }

        try {
            DB::beginTransaction();
            $process->update([
                'make_qty'      => DB::raw("make_qty - {$processDetail->report_qty}"),
                'total_hours'   => DB::raw("total_hours - {$processDetail->total_hours}"),
            ]);
            $processDetail->update([
                'deletor_id' => UnitService::getUserId(),
                'deleted_at' => time()
            ]);
            DB::commit();
            return true;
        }catch (\Exception $e){
            DB::rollBack();
            throw $e;
        }

    }

}
